home *** CD-ROM | disk | FTP | other *** search
- /*
- * jrdppm.c
- *
- * Copyright (C) 1991, 1992, Thomas G. Lane.
- * This file is part of the Independent JPEG Group's software.
- * For conditions of distribution and use, see the accompanying README file.
- *
- * This file contains routines to read input images in PPM format.
- * The PBMPLUS library is NOT required to compile this software,
- * but it is highly useful as a set of PPM image manipulation programs.
- *
- * These routines may need modification for non-Unix environments or
- * specialized applications. As they stand, they assume input from
- * an ordinary stdio stream. They further assume that reading begins
- * at the start of the file; input_init may need work if the
- * user interface has already read some data (e.g., to determine that
- * the file is indeed PPM format).
- *
- * These routines are invoked via the methods get_input_row
- * and input_init/term.
- */
-
- #include "jinclude.h"
-
- #ifdef PPM_SUPPORTED
-
-
- static JSAMPLE * rescale; /* => maxval-remapping array, or NULL */
-
-
- /* Portions of this code are based on the PBMPLUS library, which is:
- **
- ** Copyright (C) 1988 by Jef Poskanzer.
- **
- ** Permission to use, copy, modify, and distribute this software and its
- ** documentation for any purpose and without fee is hereby granted, provided
- ** that the above copyright notice appear in all copies and that both that
- ** copyright notice and this permission notice appear in supporting
- ** documentation. This software is provided "as is" without express or
- ** implied warranty.
- */
-
-
- LOCAL int
- pbm_getc (FILE * file)
- /* Read next char, skipping over any comments */
- /* A comment/newline sequence is returned as a newline */
- {
- register int ch;
-
- ch = getc(file);
- if (ch == '#') {
- do {
- ch = getc(file);
- } while (ch != '\n' && ch != EOF);
- }
- return ch;
- }
-
-
- LOCAL unsigned int
- read_pbm_integer (compress_info_ptr cinfo)
- /* Read an unsigned decimal integer from the PPM file */
- /* Swallows one trailing character after the integer */
- /* Note that on a 16-bit-int machine, only values up to 64k can be read. */
- /* This should not be a problem in practice. */
- {
- register int ch;
- register unsigned int val;
-
- /* Skip any leading whitespace */
- do {
- ch = pbm_getc(cinfo->input_file);
- if (ch == EOF)
- ERREXIT(cinfo->emethods, "Premature EOF in PPM file");
- } while (ch == ' ' || ch == '\t' || ch == '\n');
-
- if (ch < '0' || ch > '9')
- ERREXIT(cinfo->emethods, "Bogus data in PPM file");
-
- val = ch - '0';
- while ((ch = pbm_getc(cinfo->input_file)) >= '0' && ch <= '9') {
- val *= 10;
- val += ch - '0';
- }
- return val;
- }
-
-
- /*
- * Read one row of pixels.
- *
- * We provide several different versions depending on input file format.
- * In all cases, input is scaled to the size of JSAMPLE; it's possible that
- * when JSAMPLE is 12 bits, this would not really be desirable.
- *
- * Note that a really fast path is provided for reading raw files with
- * maxval = MAXJSAMPLE, which is the normal case (at least for 8-bit JSAMPLEs).
- */
-
-
- METHODDEF void
- get_text_gray_row (compress_info_ptr cinfo, JSAMPARRAY pixel_row)
- /* This version is for reading text-format PGM files with any maxval */
- {
- register JSAMPROW ptr0;
- register unsigned int val;
- register long col;
-
- ptr0 = pixel_row[0];
- for (col = cinfo->image_width; col > 0; col--) {
- val = read_pbm_integer(cinfo);
- if (rescale != NULL)
- val = rescale[val];
- *ptr0++ = (JSAMPLE) val;
- }
- }
-
-
- METHODDEF void
- get_text_rgb_row (compress_info_ptr cinfo, JSAMPARRAY pixel_row)
- /* This version is for reading text-format PPM files with any maxval */
- {
- register JSAMPROW ptr0, ptr1, ptr2;
- register unsigned int val;
- register long col;
-
- ptr0 = pixel_row[0];
- ptr1 = pixel_row[1];
- ptr2 = pixel_row[2];
- for (col = cinfo->image_width; col > 0; col--) {
- val = read_pbm_integer(cinfo);
- if (rescale != NULL)
- val = rescale[val];
- *ptr0++ = (JSAMPLE) val;
- val = read_pbm_integer(cinfo);
- if (rescale != NULL)
- val = rescale[val];
- *ptr1++ = (JSAMPLE) val;
- val = read_pbm_integer(cinfo);
- if (rescale != NULL)
- val = rescale[val];
- *ptr2++ = (JSAMPLE) val;
- }
- }
-
-
- METHODDEF void
- get_scaled_gray_row (compress_info_ptr cinfo, JSAMPARRAY pixel_row)
- /* This version is for reading raw-format PGM files with any maxval */
- {
- register FILE * infile = cinfo->input_file;
- register JSAMPROW ptr0;
- register long col;
-
- ptr0 = pixel_row[0];
- for (col = cinfo->image_width; col > 0; col--) {
- *ptr0++ = rescale[getc(infile)];
- }
- }
-
-
- METHODDEF void
- get_scaled_rgb_row (compress_info_ptr cinfo, JSAMPARRAY pixel_row)
- /* This version is for reading raw-format PPM files with any maxval */
- {
- register FILE * infile = cinfo->input_file;
- register JSAMPROW ptr0, ptr1, ptr2;
- register long col;
-
- ptr0 = pixel_row[0];
- ptr1 = pixel_row[1];
- ptr2 = pixel_row[2];
- for (col = cinfo->image_width; col > 0; col--) {
- *ptr0++ = rescale[getc(infile)];
- *ptr1++ = rescale[getc(infile)];
- *ptr2++ = rescale[getc(infile)];
- }
- }
-
-
- METHODDEF void
- get_raw_gray_row (compress_info_ptr cinfo, JSAMPARRAY pixel_row)
- /* This version is for reading raw-format PGM files with maxval = MAXJSAMPLE */
- {
- register FILE * infile = cinfo->input_file;
- register JSAMPROW ptr0;
- register long col;
-
- ptr0 = pixel_row[0];
- for (col = cinfo->image_width; col > 0; col--) {
- *ptr0++ = (JSAMPLE) getc(infile);
- }
- }
-
-
- METHODDEF void
- get_raw_rgb_row (compress_info_ptr cinfo, JSAMPARRAY pixel_row)
- /* This version is for reading raw-format PPM files with maxval = MAXJSAMPLE */
- {
- register FILE * infile = cinfo->input_file;
- register JSAMPROW ptr0, ptr1, ptr2;
- register long col;
-
- ptr0 = pixel_row[0];
- ptr1 = pixel_row[1];
- ptr2 = pixel_row[2];
- for (col = cinfo->image_width; col > 0; col--) {
- *ptr0++ = (JSAMPLE) getc(infile);
- *ptr1++ = (JSAMPLE) getc(infile);
- *ptr2++ = (JSAMPLE) getc(infile);
- }
- }
-
-
- /*
- * Read the file header; return image size and component count.
- */
-
- METHODDEF void
- input_init (compress_info_ptr cinfo)
- {
- int c;
- unsigned int w, h, maxval;
-
- if (getc(cinfo->input_file) != 'P')
- ERREXIT(cinfo->emethods, "Not a PPM file");
-
- c = getc(cinfo->input_file); /* save format discriminator for a sec */
-
- w = read_pbm_integer(cinfo); /* while we fetch the header info */
- h = read_pbm_integer(cinfo);
- maxval = read_pbm_integer(cinfo);
-
- switch (c) {
- case '2': /* it's a text-format PGM file */
- cinfo->methods->get_input_row = get_text_gray_row;
- cinfo->input_components = 1;
- cinfo->in_color_space = CS_GRAYSCALE;
- break;
-
- case '3': /* it's a text-format PPM file */
- cinfo->methods->get_input_row = get_text_rgb_row;
- cinfo->input_components = 3;
- cinfo->in_color_space = CS_RGB;
- break;
-
- case '5': /* it's a raw-format PGM file */
- if (maxval == MAXJSAMPLE)
- cinfo->methods->get_input_row = get_raw_gray_row;
- else
- cinfo->methods->get_input_row = get_scaled_gray_row;
- cinfo->input_components = 1;
- cinfo->in_color_space = CS_GRAYSCALE;
- break;
-
- case '6': /* it's a raw-format PPM file */
- if (maxval == MAXJSAMPLE)
- cinfo->methods->get_input_row = get_raw_rgb_row;
- else
- cinfo->methods->get_input_row = get_scaled_rgb_row;
- cinfo->input_components = 3;
- cinfo->in_color_space = CS_RGB;
- break;
-
- default:
- ERREXIT(cinfo->emethods, "Not a PPM file");
- break;
- }
-
- if (w <= 0 || h <= 0 || maxval <= 0) /* error check */
- ERREXIT(cinfo->emethods, "Not a PPM file");
-
- /* Compute the rescaling array if necessary */
- /* This saves per-pixel calculation */
- if (maxval == MAXJSAMPLE)
- rescale = NULL; /* no rescaling required */
- else {
- INT32 val, half_maxval;
-
- /* On 16-bit-int machines we have to be careful of maxval = 65535 */
- rescale = (JSAMPLE *) (*cinfo->emethods->alloc_small)
- ((size_t) (((long) maxval + 1L) * SIZEOF(JSAMPLE)));
- half_maxval = maxval / 2;
- for (val = 0; val <= (INT32) maxval; val++) {
- /* The multiplication here must be done in 32 bits to avoid overflow */
- rescale[val] = (JSAMPLE) ((val * MAXJSAMPLE + half_maxval) / maxval);
- }
- }
-
- cinfo->image_width = w;
- cinfo->image_height = h;
- cinfo->data_precision = BITS_IN_JSAMPLE;
- }
-
-
- /*
- * Finish up at the end of the file.
- */
-
- METHODDEF void
- input_term (compress_info_ptr cinfo)
- {
- /* no work (we let free_all release the workspace) */
- }
-
-
- /*
- * The method selection routine for PPM format input.
- * Note that this must be called by the user interface before calling
- * jpeg_compress. If multiple input formats are supported, the
- * user interface is responsible for discovering the file format and
- * calling the appropriate method selection routine.
- */
-
- GLOBAL void
- jselrppm (compress_info_ptr cinfo)
- {
- cinfo->methods->input_init = input_init;
- /* cinfo->methods->get_input_row is set by input_init */
- cinfo->methods->input_term = input_term;
- }
-
- #endif /* PPM_SUPPORTED */
-